package com.ruoyi.wms.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.utils.MapstructUtils;
import com.ruoyi.common.mybatis.core.page.PageQuery;
import com.ruoyi.common.mybatis.core.page.TableDataInfo;
import com.ruoyi.wms.domain.bo.MailboxAddressBo;
import com.ruoyi.wms.domain.entity.MailboxAddress;
import com.ruoyi.wms.domain.vo.MailboxAddressTreeSelectVo;
import com.ruoyi.wms.domain.vo.MailboxAddressVo;
import com.ruoyi.wms.mapper.MailboxAddressMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.lang.Validator.isNotNull;

/**
 * 仓库Service业务层处理
 *
 * @author zcc
 * @date 2024-07-16
 */
@RequiredArgsConstructor
@Service
public class MailboxAddressService extends ServiceImpl<MailboxAddressMapper, MailboxAddress> {

    private final MailboxAddressMapper mailboxAddressMapper;

    /**
     * 查询仓库
     */

    public MailboxAddressVo queryById(Long id) {
        return mailboxAddressMapper.selectVoById(id);
    }

    /**
     * 查询仓库列表
     */

    public TableDataInfo<MailboxAddressVo> queryPageList(MailboxAddressBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<MailboxAddress> lqw = buildQueryWrapper(bo);
        Page<MailboxAddressVo> result = mailboxAddressMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询仓库列表
     */
    public List<MailboxAddressVo> queryList(MailboxAddressBo bo) {
        LambdaQueryWrapper<MailboxAddress> lqw = buildQueryWrapper(bo);
        return mailboxAddressMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<MailboxAddress> buildQueryWrapper(MailboxAddressBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<MailboxAddress> lqw = Wrappers.lambdaQuery();
        lqw.eq(StrUtil.isNotBlank(bo.getCode()), MailboxAddress::getCode, bo.getCode());
        lqw.like(StrUtil.isNotBlank(bo.getName()), MailboxAddress::getName, bo.getName());
        lqw.orderByAsc(MailboxAddress::getOrderNum);
        return lqw;
    }

    /**
     * 新增仓库
     */

    public void insertByBo(MailboxAddressBo bo) {
        validateMailboxAddressNameAndNo(bo);
        MailboxAddress add = MapstructUtils.convert(bo, MailboxAddress.class);
        add.setOrderNum(this.getNextOrderNum());
        mailboxAddressMapper.insert(add);
    }

    private Long getNextOrderNum() {
        LambdaQueryWrapper<MailboxAddress> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(MailboxAddress::getOrderNum);
        wrapper.last("limit 1");
        MailboxAddress warehouse = mailboxAddressMapper.selectOne(wrapper);
        return warehouse == null ? 0L : warehouse.getOrderNum() + 1;
    }

    /**
     * 修改仓库
     */

    public void updateByBo(MailboxAddressBo bo) {
        validateMailboxAddressNameAndNo(bo);
        MailboxAddress update = MapstructUtils.convert(bo, MailboxAddress.class);
        mailboxAddressMapper.updateById(update);
    }

    private void validateMailboxAddressNameAndNo(MailboxAddressBo warehouse) {
        LambdaQueryWrapper<MailboxAddress> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(MailboxAddress::getName, warehouse.getName()).or().eq(StrUtil.isNotBlank(warehouse.getCode()), MailboxAddress::getCode, warehouse.getCode());
        List<MailboxAddress> warehouseList = mailboxAddressMapper.selectList(queryWrapper);
        boolean validateNameResult = warehouseList.stream().anyMatch(
            it -> Objects.equals(it.getName(), warehouse.getName()) && !Objects.equals(it.getId(), warehouse.getId()));
        Assert.isFalse(validateNameResult, "名称重复");
        boolean validateNoResult = warehouseList.stream().anyMatch(
            it -> Objects.equals(it.getCode(), warehouse.getCode()) && !Objects.equals(it.getId(), warehouse.getId()));
        Assert.isFalse(validateNoResult, "编号重复");
    }

    /**
     * 删除仓库
     */

    public void deleteById(Long id) {
        mailboxAddressMapper.deleteById(id);
    }

    /**
     * 批量删除仓库
     */

    public void deleteByIds(Collection<Long> ids) {
        mailboxAddressMapper.deleteBatchIds(ids);
    }

    @Transactional(rollbackFor = {Exception.class})
    public void updateOrderNum(List<MailboxAddressBo> tree) {
        if (CollUtil.isEmpty(tree)) {
            return;
        }
        List<MailboxAddress> updateList = MapstructUtils.convert(tree, MailboxAddress.class);
        for (int i = 0; i < updateList.size(); i++) {
            updateList.get(i).setOrderNum((long) i);
        }
        saveOrUpdateBatch(updateList);
    }

    /**
     * @param itemTypes
     * @return
     */

    public List<MailboxAddressTreeSelectVo> buildItemTypeTreeSelect(List<MailboxAddressVo> itemTypes) {
        List<MailboxAddressVo> itemTypeTrees = buildDeptTree(itemTypes);
        return itemTypeTrees.stream().map(MailboxAddressTreeSelectVo::new).collect(Collectors.toList());
    }

    /**
     * 构建前端所需要树结构
     *
     * @param itemTypes 部门列表
     * @return 树结构列表
     */
    private List<MailboxAddressVo> buildDeptTree(List<MailboxAddressVo> itemTypes) {
        List<MailboxAddressVo> returnList = new ArrayList<>();
        List<Long> tempList = new ArrayList<Long>();
        for (MailboxAddressVo dept : itemTypes) {
            tempList.add(dept.getId());
        }
        for (MailboxAddressVo dept : itemTypes) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(itemTypes, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = itemTypes;
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<MailboxAddressVo> list, MailboxAddressVo t) {
        // 得到子节点列表
        List<MailboxAddressVo> childList = getChildList(list, t);
        t.setChildren(childList);
        for (MailboxAddressVo tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<MailboxAddressVo> getChildList(List<MailboxAddressVo> list, MailboxAddressVo t) {
        List<MailboxAddressVo> tlist = new ArrayList<>();
        for (MailboxAddressVo n : list) {
            if (isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<MailboxAddressVo> list, MailboxAddressVo t) {
        return getChildList(list, t).size() > 0;
    }
}
